package com.such.kit.io.support;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import com.such.kit.Callable;
import com.such.kit.io.simple.support.IOSimple;
import com.such.kit.io.source.DatabaseIOSource;
import com.such.kit.io.source.MemoryIOSource;
import com.such.kit.message.bean.Messager;
import com.such.kit.message.bean.MessageItem;
import com.such.kit.placeholder.PlaceholderCommons;
import com.such.kit.validate.ValidateCommons;

/**
 * @author SUCH
 * <pre>
 * IO 数据源抽象类
 * 通过 IOSource 的不同实现可以指定不同数据源，如：{@link DatabaseIOSource}、{@link MemoryIOSource}
 * 
 * 通过继承、重写 doInput、doOutput 方法实现不同数据源数据的导入、导出特性
 * </pre>
 */
public abstract class IOSource {

	/** AUTO_REPLACE_KEY_IDENTITY：[作用于全局] 被替换为 {@link UUID} */
	public static final String AUTO_REPLACE_G_KEY_IDENTITY = "G_IDENTITY";
	/** AUTO_REPLACE_KEY_IDENTITY：[作用于数据] 被替换为 {@link UUID} */
	public static final String AUTO_REPLACE_D_KEY_IDENTITY = "D_IDENTITY";

	/** batchSize：批量处理时，每个批次最大数量 */
	protected int batchSize = 10000;
	/**
	 * messager：消息发送器
	 * <pre>
	 * 可以根据实际需求将 IOSource 内部的异常、警告等信息进行管理，方便外部读取、处理
	 * 
	 * 为了保证 Messager 的可控性，设定最多存储 100 条 {@link MessageItem 记录}
	 * </pre>
	 */
	protected Messager<Map<String, Object>> messager = new Messager<Map<String, Object>>(100);

	private Map<String, String> autoReplaceMap = new HashMap<String, String>();

	public IOSource() {
		this.autoReplaceMap.put(AUTO_REPLACE_G_KEY_IDENTITY, UUID.randomUUID().toString());
	}

	/** [参考 {@link #batchSize}] */
	public void setBatchSize(int batchSize) {
		this.batchSize = batchSize;
	}

	/**
	 * <pre>
	 * 此方法需要进行重写实现
	 * 
	 * inputExpression 在不同的 IOSource 实现中具有不同含义，具体参考各实现的说明
	 * lastBatch 提供了一种批量处理方式，需要重点实现
	 * </pre>
	 * @param inputExpression 导入表达式
	 * @param params 参数集
	 * @param lastBatch 是否最后的批次
	 * @param extraParams 扩展参数，不同的实现可能有不同的扩展
	 */
	public abstract void doInput(String inputExpression, Map<String, Object> params, boolean lastBatch, Map<String, Object> extraParams);

	/**
	 * <pre>
	 * 此方法需要进行重写实现
	 * 
	 * outputExpression 在不同的 IOSource 实现中具有不同含义，具体参考各实现的说明
	 * caller 的入参为每条数据
	 * </pre>
	 * @param outputExpression 导出表达式
	 * @param params 参数集
	 * @param caller 数据处理回调
	 * @throws Exception
	 */
	public abstract void doOutput(String outputExpression, Map<String, Object> params, Callable<Map<String, Object>, Boolean> caller) 
			throws Exception;

	/**
	 * <pre>
	 * 对参数集中特殊的保留字进行转换，参数支持使用 {@link PlaceholderCommons 占位符} 生成复杂值
	 * 设计初衷在于对 {@link IOSimple#args 自定义参数集} 进行功能性补强，可以通过保留字传入动态值
	 * 
	 * [保留字] 列表
	 *   {@link #AUTO_REPLACE_G_KEY_IDENTITY}
	 *   {@link #AUTO_REPLACE_D_KEY_IDENTITY}
	 * 
	 * [保留字] 作用域
	 *   [作用于全局] IOSource 实例被创建时进行转换
	 *   [作用于数据] 处理每条数据时进行转换
	 * </pre>
	 * @param params 参数集
	 */
	protected void autoReplace(Map<String, Object> params) {
		if (ValidateCommons.isNotEmpty(params)) {
			this.autoReplaceMap.put(AUTO_REPLACE_D_KEY_IDENTITY, UUID.randomUUID().toString());

			for (Entry<String, Object> entry : params.entrySet()) {
				String key = entry.getKey();
				Object obj = entry.getValue();
				if (obj instanceof String) {
					String value = (String) obj;
					if (AUTO_REPLACE_G_KEY_IDENTITY.equals(value) || AUTO_REPLACE_D_KEY_IDENTITY.equals(value)) {
						params.put(key, this.autoReplaceMap.get(value));
					} else {
						params.put(key, PlaceholderCommons.replacePlaceholder(value, this.autoReplaceMap));
					}
				}
			}
		}
	}

	/** [参考 {@link #messager}] */
	public Messager<Map<String, Object>> getMessager() {
		return this.messager;
	}

}
